home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrtools-1.10 / lib / getargs.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-28  |  18.2 KB  |  745 lines

  1. /* @(#)getargs.c    2.28 00/05/20 Copyright 1985, 1988, 1995 J. Schilling */
  2. #ifndef lint
  3. static    char sccsid[] =
  4.     "@(#)getargs.c    2.28 00/05/20 Copyright 1985, 1988, 1995 J. Schilling";
  5. #endif
  6. #define    NEW
  7. /*
  8.  *    Copyright (c) 1985, 1988, 1995 J. Schilling
  9.  *
  10.  *    1.3.88     Start implementation of release 2
  11.  */
  12. /*
  13.  *    Parse arguments on a command line.
  14.  *    Format string specifier (appearing directly after flag name):
  15.  *        ''    BOOL
  16.  *        '*'    string
  17.  *        '?'    char
  18.  *        '#'    number
  19.  *        '&'    call function
  20.  *        '+'    inctype        +++ NEU +++
  21.  */
  22. /*
  23.  * This program is free software; you can redistribute it and/or modify
  24.  * it under the terms of the GNU General Public License as published by
  25.  * the Free Software Foundation; either version 2, or (at your option)
  26.  * any later version.
  27.  *
  28.  * This program is distributed in the hope that it will be useful,
  29.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  30.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  31.  * GNU General Public License for more details.
  32.  *
  33.  * You should have received a copy of the GNU General Public License
  34.  * along with this program; see the file COPYING.  If not, write to
  35.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  36.  */
  37. /* LINTLIBRARY */
  38. #include <mconfig.h>
  39. #include <standard.h>
  40. #include <getargs.h>
  41. #include <ctype.h>
  42. #include <vadefs.h>
  43. #include <strdefs.h>
  44. #include <schily.h>
  45.  
  46. #define    NOARGS          0    /* No more args            */
  47. #define    NOTAFLAG      1    /* Not a flag type argument    */
  48. #define BADFLAG        (-1)    /* Not a valid flag argument    */
  49. #define BADFMT        (-2)    /* Error in format string    */
  50. #define NOTAFILE    (-3)    /* Seems to be a flag type arg    */
  51.  
  52.  
  53.     int    _getargs __PR((int *, char *const **, const char *,
  54.                             BOOL, va_list));
  55. LOCAL    int    dofile __PR((int *, char *const **, const char **));
  56. LOCAL    int    doflag __PR((int *, char *const **, const char *,
  57.                         const char *, BOOL, va_list));
  58. LOCAL    int    dosflags __PR((const char *, const char *, BOOL, va_list));
  59. LOCAL    int    checkfmt __PR((const char *));
  60. LOCAL    int    checkeql __PR((const char *));
  61.  
  62. LOCAL    va_list    va_dummy;
  63.  
  64. LOCAL    char    fmtspecs[] = "#?*&+"; 
  65.  
  66. #define    isfmtspec(c)        (strchr(fmtspecs, c) != NULL)
  67.  
  68. /*---------------------------------------------------------------------------
  69. |
  70. |    get flags until a non flag type argument is reached
  71. |
  72. +---------------------------------------------------------------------------*/
  73. /* VARARGS3 */
  74. #ifdef    PROTOTYPES
  75. int getargs(int *pac, char *const **pav, const char *fmt, ...)
  76. #else
  77. int getargs(pac, pav, fmt, va_alist)
  78.     int    *pac;
  79.     char    **pav[];
  80.     char    *fmt;
  81.     va_dcl
  82. #endif
  83. {
  84.     va_list    args;
  85.     int    ret;
  86.  
  87. #ifdef    PROTOTYPES
  88.     va_start(args, fmt);
  89. #else
  90.     va_start(args);
  91. #endif
  92.     ret = _getargs(pac, pav, fmt, TRUE, args);
  93.     va_end(args);
  94.     return (ret);
  95. }
  96.  
  97.  
  98. /*---------------------------------------------------------------------------
  99. |
  100. |    get all flags on the command line, do not stop on files
  101. |
  102. +---------------------------------------------------------------------------*/
  103. /* VARARGS3 */
  104. #ifdef    PROTOTYPES
  105. int getallargs(int *pac, char *const **pav, const char *fmt, ...)
  106. #else
  107. int getallargs(pac, pav, fmt, va_alist)
  108.     int    *pac;
  109.     char    **pav[];
  110.     char    *fmt;
  111.     va_dcl
  112. #endif
  113. {
  114.     va_list    args;
  115.     int    ret;
  116.  
  117. #ifdef    PROTOTYPES
  118.     va_start(args, fmt);
  119. #else
  120.     va_start(args);
  121. #endif
  122.     for (;; (*pac)--, (*pav)++) {
  123.         if ((ret = _getargs(pac, pav, fmt, TRUE, args)) != NOTAFLAG)
  124.             break;
  125.     }
  126.     va_end(args);
  127.     return (ret);
  128. }
  129.  
  130.  
  131. /*---------------------------------------------------------------------------
  132. |
  133. |    get next non flag type argument (i.e. a file)
  134. |
  135. +---------------------------------------------------------------------------*/
  136. int getfiles(pac, pav, fmt)
  137.     int        *pac;
  138.     char *const    *pav[];
  139.     const char    *fmt;
  140. {
  141.     return (_getargs(pac, pav, fmt, FALSE, va_dummy));
  142. }
  143.  
  144.  
  145. /*---------------------------------------------------------------------------
  146. |
  147. |    check args until the next non flag type argmument is reached
  148. |    *pac is decremented, *pav is incremented so that the
  149. |    non flag type argument is at *pav[0]
  150. |
  151. |    return code:
  152. |        NOARGS        no more args
  153. |        NOTAFLAG    not a flag type argument
  154. |        BADFLAG        a non-matching flag type argument
  155. |        BADFMT        bad syntax in format string
  156. |
  157. |
  158. +---------------------------------------------------------------------------*/
  159. /*LOCAL*/ int _getargs(pac, pav, fmt, setargs, args)
  160.     register int        *pac;
  161.     register char    *const    **pav;
  162.          const char    *fmt;
  163.         BOOL        setargs;
  164.         va_list        args;
  165. {
  166.     const     char    *argp;
  167.          int    ret;
  168.  
  169.  
  170.     for(; *pac > 0; (*pac)--, (*pav)++) {
  171.         argp = **pav;
  172.  
  173.         ret = dofile(pac, pav, &argp);
  174.  
  175.         if (ret != NOTAFILE)
  176.             return (ret);
  177.  
  178.         ret = doflag(pac, pav, argp, fmt, setargs, args);
  179.  
  180.         if (ret != NOTAFLAG)
  181.             return (ret);
  182.     }
  183.     return (NOARGS);
  184. }
  185.  
  186.  
  187. /*---------------------------------------------------------------------------
  188. |
  189. | check if *pargp is a file type argument
  190. |
  191. +---------------------------------------------------------------------------*/
  192. LOCAL int dofile(pac, pav, pargp)
  193.     register int        *pac;
  194.     register char *const    **pav;
  195.          const char    **pargp;
  196. {
  197.     register const char    *argp = *pargp;
  198.  
  199.  
  200.     if (argp[0] == '-') {
  201.         /*
  202.          * "-" is a special non flag type argument
  203.          *     that usually means take stdin instead of a named file
  204.          */
  205.         if (argp[1] == '\0')
  206.             return (NOTAFLAG);
  207.         /*
  208.          * "--" is a prefix to take the next argument
  209.          *    as non flag type argument
  210.          * NOTE: Posix requires "--" to indicate the end of the
  211.          *     flags on the command line. But we are currently not
  212.          *     Posix.
  213.          */
  214.         if (argp[1] == '-' && argp[2] == '\0') {
  215.             if (--(*pac) > 0) {
  216.                 (*pav)++;
  217.                 return (NOTAFLAG);
  218.             } else {
  219.                 return (NOARGS);
  220.             }
  221.         }
  222.     }
  223.  
  224.     /*
  225.      * now check if it may be flag type argument
  226.      * flag type arguments begin with a '-', a '+' or contain a '='
  227.      * i.e. -flag +flag or flag=
  228.      */
  229.     if (argp[0] != '-' && argp[0] != '+' && (!checkeql(argp)))
  230.         return (NOTAFLAG);
  231.  
  232.     return (NOTAFILE);
  233. }
  234.  
  235.  
  236. /*---------------------------------------------------------------------------
  237. |
  238. |    compare argp with the format string
  239. |    if a match is found store the result a la scanf in one of the
  240. |    arguments pointed to in the va_list
  241. |
  242. |    If setargs is FALSE, only check arguments for getfiles()
  243. |    in this case, va_list may be a dummy arg.
  244. |
  245. +---------------------------------------------------------------------------*/
  246. LOCAL int doflag(pac, pav, argp, fmt, setargs, oargs)
  247.         int        *pac;
  248.         char    *const    **pav;
  249.     register const char    *argp;
  250.     register const char    *fmt;
  251.         BOOL        setargs;
  252.         va_list        oargs;
  253. {
  254.     long    val;
  255.     int    singlecharflag    = 0;
  256.     BOOL    isspec;
  257.     BOOL    hasdash        = FALSE;
  258.     BOOL    doubledash    = FALSE;
  259.     BOOL    haseql        = checkeql(argp);
  260.     const char    *sargp;
  261.     const char    *sfmt    = fmt;
  262.     va_list    args;
  263.     char    *const    *spav    = *pav;
  264.     int        spac    = *pac;
  265.     void        *curarg    = (void *)0;
  266.  
  267.     /*
  268.      * flags beginning with '-' don't have to include the '-' in
  269.      * the format string.
  270.      * flags beginning with '+' have to include it in the format string.
  271.      */
  272.     if (argp[0] == '-') {
  273.         argp++;
  274.         hasdash = TRUE;
  275.         /*
  276.          * Implement legacy support for --longopt
  277.          * If we find a double dash, we do not look for combinations
  278.          * of boolean single char flags.
  279.          */
  280.         if (argp[0] == '-') {
  281.             argp++;
  282.             doubledash = TRUE;
  283.             /*
  284.              * Allow -- only for long options.
  285.              */
  286.             if (argp[1] == '\0') {
  287.                 return (BADFLAG);
  288.             }
  289.         }
  290.     }
  291.     sargp = argp;
  292.  
  293.     /*
  294.      * Initialize 'args' to the start of the argument list.
  295.      * I don't know any portable way to copy an arbitrary
  296.      * C object so I use a system-specific routine
  297.      * (probably a macro) from stdarg.h.  (Remember that
  298.      * if va_list is an array, 'args' will be a pointer
  299.      * and '&args' won't be what I would need for memcpy.)
  300.      * It is a system requirement for SVr4 compatibility
  301.      * to be able to do this assgignement. If your system
  302.      * defines va_list to be an array but does not define
  303.      * va_copy() you are lost.
  304.      * This is needed to make sure, that 'oargs' will not
  305.      * be clobbered.
  306.      */
  307.     va_copy(args, oargs);
  308.  
  309.     if (setargs)
  310.         curarg = va_arg(args, void *);
  311.  
  312.     /*
  313.      * check if the first flag in format string is a singlechar flag
  314.      */
  315.     if (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0')
  316.         singlecharflag++;
  317.     /*
  318.      * check the whole format string for a match
  319.      */
  320.     for(;;) {
  321.         for(;*fmt; fmt++,argp++) {
  322.             if (*fmt == '\\') {
  323.                 /*
  324.                  * Allow "#?*&+" to appear inside a flag.
  325.                  * NOTE: they must be escaped by '\\' only
  326.                  *     inside the the format string.
  327.                  */
  328.                 fmt++;
  329.                 isspec = FALSE;
  330.             } else {
  331.                 isspec = isfmtspec(*fmt);
  332.             }
  333.             /*
  334.              * If isspec is TRUE, the arg beeing checked starts
  335.              * like a valid flag. Argp now points to the rest.
  336.              */
  337.             if (isspec) {
  338.                 /*
  339.                  * If *argp is '+' and we are on the
  340.                  * beginning of the arg that is currently
  341.                  * checked, this cannot be an inc type flag.
  342.                  */
  343.                 if (*argp == '+' && argp == sargp)
  344.                     continue;
  345.                 /*
  346.                  * skip over to arg of flag
  347.                  */
  348.                 if (*argp == '=') {
  349.                     argp++;
  350.                 } else if (*argp != '\0' && haseql) {
  351.                     /*
  352.                      * Flag and arg are not separated by a
  353.                      * space.
  354.                      * Check here for:
  355.                      * xxxxx=yyyyy    match on '&'
  356.                      * Checked before:
  357.                      * abc=yyyyy    match on 'abc&'
  358.                      *         or     'abc*' 
  359.                      *         or     'abc#' 
  360.                      * We come here if 'argp' starts with
  361.                      * the same sequence as a valid flag
  362.                      * and contains an equal sign.
  363.                      * We have tested before if the text
  364.                      * before 'argp' matches exactly.
  365.                      * At this point we have no exact match
  366.                      * and we only allow to match
  367.                      * the special pattern '&'.
  368.                      * We need this e.g. for 'make'.
  369.                      * We allow any flag type argument to
  370.                      * match the format string "&" to set
  371.                      * up a function that handles all odd
  372.                      * stuff that getargs will not grok.
  373.                      * In addition, to allow getargs to be
  374.                      * used for CPP type flags we allow to
  375.                      * match -Dabc=xyz on 'D&'. Note that
  376.                      * Dabc=xyz will not match 'D&'.
  377.                      */
  378.                     if ((!hasdash && argp != sargp) || *fmt != '&')
  379.                         goto nextarg;
  380.                 }
  381.                 /*
  382.                  * *arpp == '\0' || !haseql
  383.                  * We come here if 'argp' starts with
  384.                  * the same sequence as a valid flag.
  385.                  * This will match on the following args:
  386.                  * -farg    match on 'f*'
  387.                  * -f12        match on 'f#'
  388.                  * +12        match on '+#'
  389.                  * -12        match on '#'
  390.                  * and all args that are separated from
  391.                  * their flags.
  392.                  * In the switch statement below, we check
  393.                  * if the text after 'argp' (if *argp != 0) or
  394.                  * the next arg is a valid arg for this flag.
  395.                   */
  396.                 break;
  397.             } else if (*fmt == *argp) {
  398.                 if (argp[1] == '\0' &&
  399.                     (fmt[1] == '\0' || fmt[1] == ',')) {
  400.  
  401.                     if (setargs)
  402.                         *((int *)curarg) = TRUE;
  403.  
  404.  
  405.                     return (checkfmt(fmt));/* XXX */
  406.                 }
  407.             } else {
  408.                 /*
  409.                  * skip over to next format identifier
  410.                  * & reset arg pointer
  411.                  */
  412.             nextarg:
  413.                 while (*fmt != ',' && *fmt != '\0') {
  414.                     /* function has extra arg on stack */
  415.                     if (*fmt == '&' && setargs)
  416.                         curarg = va_arg(args, void *);
  417.                     fmt++;
  418.                 }
  419.                 argp = sargp;
  420.                 break;
  421.             }
  422.         }
  423.         switch(*fmt) {
  424.  
  425.         case '\0':
  426.             /*
  427.              * Boolean type has been tested before.
  428.              */
  429.             if (singlecharflag && !doubledash &&
  430.                (val = dosflags(sargp, sfmt, setargs, oargs)) !=
  431.                                 BADFLAG)
  432.                 return (val);
  433.  
  434.  
  435.             return (BADFLAG);
  436.  
  437.         case ',':
  438.             fmt++;
  439.             if (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0')
  440.                 singlecharflag++;
  441.             if (setargs)
  442.                 curarg = va_arg(args, void *);
  443.             continue;
  444.  
  445.         case '*':
  446.             if (*argp == '\0') {
  447.                 if (*pac > 1) {
  448.                     (*pac)--;
  449.                     (*pav)++;
  450.                     argp = **pav;
  451.                 } else {
  452.                     return (BADFLAG);
  453.                 }
  454.             }
  455.             if (setargs)
  456.                 *((const char **)curarg) = argp;
  457.  
  458.  
  459.             return (checkfmt(fmt));
  460.  
  461.         case '?':
  462.             /*
  463.              * If more than one char arg, it
  464.              * cannot be a character argument.
  465.              */
  466.             if (argp[1] != '\0')
  467.                 goto nextchance;
  468.             if (setargs)
  469.                 *((char *)curarg) = *argp;
  470.  
  471.  
  472.             return (checkfmt(fmt));
  473.  
  474.         case '+':
  475.             /*
  476.              * inc type is similar to boolean,
  477.              * there is no arg in argp to convert.
  478.              */
  479.             if (*argp != '\0')
  480.                 goto nextchance;
  481.             /*
  482.              * If *fmt is '+' and we are on the beginning
  483.              * of the format desciptor that is currently
  484.              * checked, this cannot be an inc type flag.
  485.              */
  486.             if (fmt == sfmt || fmt[-1] == ',')
  487.                 goto nextchance;
  488.  
  489.             if (fmt[1] == 'l' || fmt[1] == 'L') {
  490.                 if (setargs)
  491.                     *((long *)curarg) += 1;
  492.                 fmt++;
  493.             } else if (fmt[1] == 's' || fmt[1] == 'S') {
  494.                 if (setargs)
  495.                     *((short *)curarg) += 1;
  496.                 fmt++;
  497.             } else {
  498.                 if (fmt[1] == 'i' || fmt[1] == 'I')
  499.                     fmt++;
  500.                 if (setargs)
  501.                     *((int *)curarg) += 1;
  502.             }
  503.  
  504.  
  505.             return (checkfmt(fmt));
  506.  
  507.         case '#':
  508.             if (*argp == '\0') {
  509.                 if (*pac > 1) {
  510.                     (*pac)--;
  511.                     (*pav)++;
  512.                     argp = **pav;
  513.                 } else {
  514.                     return (BADFLAG);
  515.                 }
  516.             }
  517.             if (*astol(argp, &val) != '\0') {
  518.                 /*
  519.                  * arg is not a valid number!
  520.                  * go to next format in the format string
  521.                  * and check if arg matches any other type
  522.                  * in the format specs.
  523.                  */
  524.             nextchance:
  525.                 while(*fmt != ',' && *fmt != '\0') {
  526.                     if (*fmt == '&' && setargs)
  527.                         curarg = va_arg(args, void *);
  528.                     fmt++;
  529.                 }
  530.                 argp = sargp;
  531.                 *pac = spac;
  532.                 *pav = spav;
  533.                 continue;
  534.             }
  535.             if (fmt[1] == 'l' || fmt[1] == 'L') {
  536.                 if (setargs)
  537.                     *((long *)curarg) = val;
  538.                 fmt++;
  539.             } else if (fmt[1] == 's' || fmt[1] == 'S') {
  540.                 if (setargs)
  541.                     *((short *)curarg) = val;
  542.                 fmt++;
  543.             } else {
  544.                 if (fmt[1] == 'i' || fmt[1] == 'I')
  545.                     fmt++;
  546.                 if (setargs)
  547.                     *((int *)curarg) = val;
  548.             }
  549.  
  550.             return (checkfmt(fmt));
  551.  
  552.         case '&':
  553.             if (*argp == '\0') {
  554.                 if (*pac > 1) {
  555.                     (*pac)--;
  556.                     (*pav)++;
  557.                     argp = **pav;
  558.                 } else {
  559.                     return (BADFLAG);
  560.                 }
  561.             }
  562.  
  563.             if ((val = checkfmt(fmt)) != NOTAFLAG)
  564.                 return (val);
  565.  
  566.             if (setargs) {
  567.                 int    ret;
  568.                 void    *funarg = va_arg(args, void *);
  569.  
  570.                 ret = ((*(getargfun)curarg) (argp, funarg));
  571.                 if (ret != NOTAFILE)
  572.                     return (ret);
  573.                 fmt++;
  574.             } else {
  575.                 return (val);
  576.             }
  577.             /*
  578.              * Called function returns NOTAFILE: try next format.
  579.              */
  580.         }
  581.     }
  582. }
  583.  
  584.  
  585. /*---------------------------------------------------------------------------
  586. |
  587. |    parse args for combined single char flags
  588. |
  589. +---------------------------------------------------------------------------*/
  590. typedef struct {
  591.     void    *curarg;
  592.     short    count;
  593.     char    c;
  594.     char    type;
  595. } sflags;
  596.  
  597. LOCAL int dosflags(argp, fmt, setargs, oargs)
  598.     register const char    *argp;
  599.     register const char    *fmt;
  600.         BOOL        setargs;
  601.         va_list        oargs;
  602. {
  603. #define    MAXSF    32
  604.          sflags    sf[MAXSF];
  605.          va_list args;
  606.     register sflags    *rsf    = sf;
  607.     register int    nsf    = 0;
  608.     register const char *p    = argp;
  609.     register int    i;
  610.     register void    *curarg = (void *)0;
  611.  
  612.     /*
  613.      * Initialize 'args' to the start of the argument list.
  614.      * I don't know any portable way to copy an arbitrary
  615.      * C object so I use a system-specific routine
  616.      * (probably a macro) from stdarg.h.  (Remember that
  617.      * if va_list is an array, 'args' will be a pointer
  618.      * and '&args' won't be what I would need for memcpy.)
  619.      * It is a system requirement for SVr4 compatibility
  620.      * to be able to do this assgignement. If your system
  621.      * defines va_list to be an array but does not define
  622.      * va_copy() you are lost.
  623.      * This is needed to make sure, that 'oargs' will not
  624.      * be clobbered.
  625.      */
  626.     va_copy(args, oargs);
  627.  
  628.     if (setargs)
  629.         curarg = va_arg(args, void *);
  630.  
  631.     while (*p) {
  632.         for (i=0; i < nsf; i++) {
  633.             if (rsf[i].c == *p)
  634.                 break;
  635.         }
  636.         if (i >= MAXSF)
  637.             return (BADFLAG);
  638.         if (i == nsf) {
  639.             rsf[i].curarg = (void *)0;
  640.             rsf[i].count = 0;
  641.             rsf[i].c = *p;
  642.             rsf[i].type = (char)-1;
  643.             nsf++;
  644.         }
  645.         rsf[i].count++;
  646.         p++;
  647.     }
  648.  
  649.     while (*fmt) {
  650.         if (!isfmtspec(*fmt) &&
  651.             (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0') &&
  652.              strchr(argp, *fmt)) {
  653.             for (i=0; i < nsf; i++) {
  654.                 if (rsf[i].c == *fmt) {
  655.                     if (fmt[1] == '+') {
  656.                         fmt++;
  657.                         if (fmt[1] == ',' ||
  658.                             fmt[1] == '\0') {
  659.                             rsf[i].type = 'i';
  660.                         } else {
  661.                             rsf[i].type = fmt[1];
  662.                         }
  663.                     } else {
  664.                         rsf[i].type = fmt[1];
  665.                     }
  666.                     rsf[i].curarg = curarg;
  667.                     break;
  668.                 }
  669.             }
  670.         }
  671.         while (*fmt != ',' && *fmt != '\0') {
  672.             /* function has extra arg on stack */
  673.             if (*fmt == '&' && setargs)
  674.                 curarg = va_arg(args, void *);
  675.             fmt++;
  676.         }
  677.         if (*fmt != '\0')
  678.             fmt++;
  679.  
  680.         if (setargs)
  681.             curarg = va_arg(args, void *);
  682.     }
  683.     for (i=0; i < nsf; i++) {
  684.         if (rsf[i].type == (char)-1)
  685.             return (BADFLAG);
  686.         if (rsf[i].curarg) {
  687.             if (rsf[i].type == ',' || rsf[i].type == '\0') {
  688.                 *((int *)rsf[i].curarg) = TRUE;
  689.             } else if (rsf[i].type == 'i' || rsf[i].type == 'I') {
  690.                 *((int *)rsf[i].curarg) += rsf[i].count;
  691.             } else if (rsf[i].type == 'l' || rsf[i].type == 'L') {
  692.                 *((long *)rsf[i].curarg) += rsf[i].count;
  693.             } else if (rsf[i].type == 's' || rsf[i].type == 'S') {
  694.                 *((short *)rsf[i].curarg) += rsf[i].count;
  695.             } else {
  696.                 return (BADFLAG);
  697.             }
  698.         }
  699.     }
  700.     return (NOTAFLAG);
  701. }
  702.  
  703. /*---------------------------------------------------------------------------
  704. |
  705. |    If the next format character is a comma or the string delimiter,
  706. |    there are no invalid format specifiers. Return success.
  707. |    Otherwise raise the getarg_bad_format condition.
  708. |
  709. +---------------------------------------------------------------------------*/
  710. LOCAL int checkfmt(fmt)
  711.     const char    *fmt;
  712. {
  713.     char    c;
  714.  
  715.     c = *(++fmt);    /* non constant expression */
  716.  
  717.  
  718.     if (c == ',' || c == '\0') {
  719.         return (NOTAFLAG);
  720.     } else {
  721.         raisecond("getarg_bad_format", (long)fmt);
  722.         return (BADFMT);
  723.     }
  724. }
  725.  
  726. /*---------------------------------------------------------------------------
  727. |
  728. |    Parse the string as long as valid characters can be found.
  729. |    Valid flag identifiers are chosen from the set of
  730. |    alphanumeric characters, '-' and '_'.
  731. |    If the next character is an equal sign the string
  732. |    contains a valid flag identifier.
  733. |
  734. +---------------------------------------------------------------------------*/
  735. static int checkeql(str)
  736.     register const char *str;
  737. {
  738.     register unsigned char c;
  739.  
  740.     for (c = (unsigned char)*str;
  741.                 isalnum(c) || c == '_' || c == '-'; c = *str++)
  742.         ;
  743.     return (c == '=');
  744. }
  745.